#include "cv.h"
#include "highgui.h"
#include "ImageDepthList.h"
#include "regions.h"
#include "resize.h"

typedef __int32 Ipp32s;

#define display( name, im, flags )\
{\
	cvNamedWindow( name, flags );\
	cvShowImage( name, im );\
}

void main()
{
	ImageDepthList imdeps("C:/Data/Train400/dir.info");
	
	for( ImageDepthList::iterator iter = imdeps.begin(); iter != imdeps.end(); iter++ )
	{
		IplImage* im = cvLoadImage( iter->second.pathImage.c_str() );
		IplImage* depOrig = cvLoadImage( iter->second.pathDepth.c_str(), CV_LOAD_IMAGE_GRAYSCALE );
		IplImage* seg = cvLoadImage( iter->second.pathSegm.c_str() );

		IplImage* maskRemain = cvCreateImage( cvGetSize( im ), IPL_DEPTH_8U, 1 );
		IplImage* maskCurr = cvCreateImage( cvGetSize( im ), IPL_DEPTH_8U, 1 );
		IplImage* depth = cvCreateImage( cvGetSize( im ), depOrig->depth, depOrig->nChannels );
		IplImage* segIndex = cvCreateImage( cvGetSize( im ), IPL_DEPTH_32S, 1 );

		cvResize( depOrig, depth, CV_INTER_CUBIC );
		
		IplImage* test = cvCreateImage( cvGetSize( im ), IPL_DEPTH_8U, 1);
		resize_nnwa( depOrig, test );
		display("Test", test, 0 );
		cvSaveImage("C:/Data/Train400/test.png", test );
		for( int i = 0; i < 4; i++ )
		{
			if( depOrig ) display( "DepthOrig", depOrig, 0 );
			if( depth ) display( "Depth", depth, 0 );
			cvWaitKey(0);
		}
		cvReleaseImage( &test );

		cvSet( maskRemain, cvScalarAll(255) );

		
		CalcRegionMaskBuffer buffer( im->width*im->height );

		Ipp32s nextSegIndex = 0;

		if( seg ) display( "Segmented Image", seg, 0 );

		for( CvPoint pt = cvPoint(0,0); pt.y < im->height; pt.y++ )
		{
			unsigned char* mrem = &CV_IMAGE_ELEM( maskRemain, unsigned char, pt.y, 0 );
			for( pt.x = 0 ; pt.x < im->width; pt.x++ )
			{
				if( !mrem[pt.x] ) continue;

				calcRegionMask( seg, pt, maskCurr, maskRemain, &buffer );
				cvSet( segIndex, cvScalar( nextSegIndex ), maskCurr );
				cvSet( maskRemain, cvScalar(0), maskCurr );
				nextSegIndex++;
			}
			if( pt.y % 100 == 0 )
			{
				display( "Curr", maskCurr, 0 );
				display( "Remain", maskRemain, 0 );
				cvWaitKey( 10 );
			}
		}
		double* avgDist = new double[ nextSegIndex ];
		size_t* segSize = new size_t[ nextSegIndex ];

		for( long long i = 0; i < nextSegIndex; i++ )
		{
			avgDist[i] = 0;
			segSize[i] = 0;
		}
		
		for( int y = 0; y < im->height; y++ )
		{
			unsigned char* depr = &CV_IMAGE_ELEM( depth, unsigned char, y, 0 );
			Ipp32s* segir = &CV_IMAGE_ELEM( segIndex, Ipp32s, y, 0 );
			for( int x = 0 ; x < im->width; x++ )
			{
				Ipp32s idx = segir[x];
				assert( idx >= 0 && idx < nextSegIndex );
				avgDist[ idx ] += depr[x];
				segSize[ idx ]++;
			}
		}
		for( long long i = 0; i < nextSegIndex; i++ )
		{
			avgDist[i] /= segSize[i];
		}
		for( int y = 0; y < im->height; y++ )
		{
			unsigned char* depr = &CV_IMAGE_ELEM( depth, unsigned char, y, 0 );
			Ipp32s* segir = &CV_IMAGE_ELEM( segIndex, Ipp32s, y, 0 );
			for( int x = 0 ; x < im->width; x++ )
			{
				long long idx = segir[x];
				assert( idx >= 0 && idx < nextSegIndex );
				depr[x] = avgDist[ idx ];
			}
		}

		delete [] segSize;
		delete [] avgDist;

		if( im ) display( "Image", im, 0 );
		if( depth ) display( "Depth", depth, 0 );
		if( depOrig ) display( "DepthOrig", depOrig, 0 );
		if( seg ) display( "Segmented Image", seg, 0 );

		cvWaitKey( 0 );

		cvReleaseImage( &im );
		cvReleaseImage( &depOrig );
		cvReleaseImage( &seg );
		
		cvReleaseImage( &maskRemain );		
		cvReleaseImage( &maskCurr );	
		cvReleaseImage( &depth );
		cvReleaseImage( &segIndex );
	}
}